package com.sjj.myuser.userService;

import com.sjj.myuser.mapper.UserMapper;
import common.Result;
import org.apache.dubbo.config.annotation.Service;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import pojo.User;
import service.UserService;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * className:UserServiceImpl
 * Package:com.sjj.myuser.userService
 * Description:
 *
 * @Date: 2022/8/6 23:25
 * @Auther: wssky19890629@163.com
 */


@Component
@Service(timeout = 60000)
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;
    
    /**
     * 注册账号
     * @param user
     * @return
     */
    @Override
    public String registor(User user) throws Exception {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        //编码
        user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
        user.setUsername("无名");
        try {
            userMapper.insertUser(user);
            return "注册成功";
        } catch (Exception e){
            return "服务器异常,注册失败";
        }

    }

    /**
     * 用户改名
     * @param user
     * @return
     */
    @Override
    public Result<Object> modifyNickname(User user,String newName) {
        Result<Object> result=new Result<>();
        //先判断nickname在redis中是否存在
        String nicknameInRedis = redisTemplate.opsForValue().get(newName);
        if(nicknameInRedis!= null) {
            //存在，则判断该nickname是否被占据
            if ("exist".equals(nicknameInRedis)) {
                //被占据则返回修改失败
                result.setFlag(false);
            } else {
                tryToChangeName(result,user,newName);
            }
        } else {
            //不存在，则从数据库中读取
            User user1 = userMapper.selectUserByNickname(newName);
                //数据库不存在，则加锁修改
            if(user1==null){
                tryToChangeName(result,user,newName);
            }
                //数据库中存在，则返回修改失败
            else {
                result.setFlag(false);
            }
        }
        return result;

    }

    @Override
    public void setMsgtoRedis(String myUserId, String hisUserId, String msg) {
        String cacheId=myUserId+":"+hisUserId;
        ListOperations<String, String> stringStringListOperations = redisTemplate.opsForList();
        stringStringListOperations.leftPush(cacheId,msg);
        System.out.println(cacheId+"   "+msg);
    }

    @Override
    public List<String> getMsgFromRedis(String myUserId, String hisUserId) {
        String cacheId=hisUserId+":"+myUserId;
        ListOperations<String, String> stringStringListOperations = redisTemplate.opsForList();
        ArrayList<String> list = new ArrayList<>();
        for(long i=stringStringListOperations.size(cacheId);i>0;i--){
            list.add(stringStringListOperations.rightPop(cacheId));
        }
        list.stream().forEach(System.out::println);
        return list;
    }


    /**
     * 读取用户信息
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userMapper.getUserByUsername(username); //这里没有写密码验证等操作，直接根据username返回UserDetails(User)
    }



    public void tryToChangeName(Result<Object> result,User user,String newName){
        RLock lock = redissonClient.getLock("MYKEY"+user.getNickname());
        //加锁成功，则修改
        if(!lock.isLocked()){
            lock.lock();
            try {
                String oldName=user.getNickname();
                user.setNickname(newName);
                userMapper.updateNickname(user);
                redisTemplate.opsForValue().set(oldName,"notexist",300,TimeUnit.SECONDS);
                redisTemplate.opsForValue().set(newName,"exist",300,TimeUnit.SECONDS);
                result.setFlag(true);
            } catch (Exception e){
                e.printStackTrace();
                result.setFlag(false);
                result.setMsg("未知错误");
            } finally {
                lock.unlock();
            }
        }
        //加锁失败，则返回修改失败
        else{
            result.setFlag(false);
        }
    }


}
